# -*- coding: utf-8 -*-
"""
SmarTest 通用工具模块
"""

import atexit
import os
import sys
import uuid
import json
import logging
import datetime
from logging.handlers import RotatingFileHandler
from pathlib import Path

from common.config import LogConfig, WORK_PATH

def daemonize(pid_file=None):
    """将进程转换为守护进程"""
    try:
        # 第一次fork
        pid = os.fork()
        if pid > 0:
            # 父进程退出
            sys.exit(0)
    except OSError as e:
        logger.error(f"第一次fork失败: {e}")
        sys.exit(1)

    # 脱离父进程的控制
    os.chdir("/")
    os.setsid()
    os.umask(0)

    try:
        # 第二次fork
        pid = os.fork()
        if pid > 0:
            # 第二个父进程退出
            sys.exit(0)
    except OSError as e:
        logger.error(f"第二次fork失败: {e}")
        sys.exit(1)

    # 重定向标准文件描述符
    sys.stdout.flush()
    sys.stderr.flush()
    si = open('/dev/null', 'r')
    so = open('/dev/null', 'a+')
    se = open('/dev/null', 'a+')
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())

    # 写入PID文件
    if pid_file:
        pid = str(os.getpid())
        with open(pid_file, 'w+') as f:
            f.write(f"{pid}\n")
        atexit.register(lambda: os.remove(pid_file) if os.path.exists(pid_file) else None)

def api(name=None):
    """API装饰器，用于标记需要注册为API的方法
    
    Args:
        name (str): 自定义API名称，如果不提供则使用方法名
    """
    def decorator(func):
        func._is_api = True
        func._api_name = name or func.__name__
        return func
    return decorator

# 日志工具
class LogUtil:
    @staticmethod
    def get_logger(name):
        """获取日志记录器
        
        Args:
            name: 日志记录器名称
            
        Returns:
            logger: 日志记录器实例
        """
        logger = logging.getLogger(name)
        logger.setLevel(getattr(logging, LogConfig.LOG_LEVEL))
        
        # 确保日志目录存在
        os.makedirs(LogConfig.LOG_DIR, exist_ok=True)
        
        # 文件处理器
        log_file = os.path.join(LogConfig.LOG_DIR, f'{name}.log')
        file_handler = RotatingFileHandler(
            log_file, 
            maxBytes=LogConfig.LOG_FILE_MAX_BYTES,
            backupCount=LogConfig.LOG_FILE_BACKUP_COUNT
        )
        file_handler.setFormatter(logging.Formatter(LogConfig.LOG_FORMAT, LogConfig.LOG_DATE_FORMAT))
        logger.addHandler(file_handler)
        
        # 控制台处理器
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(logging.Formatter(LogConfig.LOG_FORMAT, LogConfig.LOG_DATE_FORMAT))
        logger.addHandler(console_handler)
        
        return logger

# 文件工具
class FileUtil:
    @staticmethod
    def ensure_dir(directory):
        """确保目录存在，不存在则创建
        
        Args:
            directory: 目录路径
        """
        os.makedirs(directory, exist_ok=True)
    
    @staticmethod
    def get_file_extension(filename):
        """获取文件扩展名
        
        Args:
            filename: 文件名
            
        Returns:
            extension: 文件扩展名（不含点号）
        """
        return os.path.splitext(filename)[1][1:].lower()
    
    @staticmethod
    def generate_unique_filename(original_filename):
        """生成唯一文件名
        
        Args:
            original_filename: 原始文件名
            
        Returns:
            unique_filename: 唯一文件名
        """
        ext = FileUtil.get_file_extension(original_filename)
        unique_id = str(uuid.uuid4())
        return f"{unique_id}.{ext}" if ext else unique_id

# JSON工具
class JsonUtil:
    @staticmethod
    def to_json(obj):
        """将对象转换为JSON字符串
        
        Args:
            obj: 要转换的对象
            
        Returns:
            json_str: JSON字符串
        """
        class CustomEncoder(json.JSONEncoder):
            def default(self, obj):
                if isinstance(obj, datetime.datetime):
                    return obj.strftime('%Y-%m-%d %H:%M:%S')
                elif isinstance(obj, datetime.date):
                    return obj.strftime('%Y-%m-%d')
                elif isinstance(obj, uuid.UUID):
                    return str(obj)
                elif hasattr(obj, '__dict__'):
                    return obj.__dict__
                return super().default(obj)
        
        return json.dumps(obj, cls=CustomEncoder, ensure_ascii=False)
    
    @staticmethod
    def from_json(json_str):
        """将JSON字符串转换为对象
        
        Args:
            json_str: JSON字符串
            
        Returns:
            obj: 转换后的对象
        """
        return json.loads(json_str)

# 时间工具
class TimeUtil:
    @staticmethod
    def get_current_time():
        """获取当前时间
        
        Returns:
            current_time: 当前时间（datetime对象）
        """
        return datetime.datetime.now()
    
    @staticmethod
    def get_current_time_str(format='%Y-%m-%d %H:%M:%S'):
        """获取当前时间字符串
        
        Args:
            format: 时间格式
            
        Returns:
            current_time_str: 当前时间字符串
        """
        return TimeUtil.get_current_time().strftime(format)
    
    @staticmethod
    def parse_time_str(time_str, format='%Y-%m-%d %H:%M:%S'):
        """解析时间字符串
        
        Args:
            time_str: 时间字符串
            format: 时间格式
            
        Returns:
            time: 解析后的时间（datetime对象）
        """
        return datetime.datetime.strptime(time_str, format)

# ID生成工具
class IdUtil:
    @staticmethod
    def generate_uuid():
        """生成UUID
        
        Returns:
            uuid: UUID字符串
        """
        return str(uuid.uuid4())
    
    @staticmethod
    def generate_short_id():
        """生成短ID
        
        Returns:
            short_id: 短ID字符串
        """
        return uuid.uuid4().hex[:8]